package com.ruoyi.api;

import com.ruoyi.common.annotation.Anonymous;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 头像上传与访问控制器
 * 支持上传图片并通过 /avatar/日期/文件名 路径访问
 */
@RestController
@CrossOrigin("*")  // 允许跨域访问
@Anonymous  // 整个控制器匿名访问，解决401问题
public class UploadController {

    // 本地存储路径（从配置文件读取）
    @Value("${file.upload.path}")
    private String uploadPath;

    // 访问URL前缀（从配置文件读取，应配置为 /avatar/）
    @Value("${file.access.url}")
    private String accessUrl;

    /**
     * 头像上传接口
     * 访问路径：POST /upload
     */
    @PostMapping("/upload")
    public Map<String, Object> uploadAvatar(
            @RequestParam("file") MultipartFile file,
            HttpServletRequest request) {

        Map<String, Object> result = new HashMap<>();

        try {
            // 1. 验证文件是否为空
            if (file.isEmpty()) {
                result.put("success", false);
                result.put("message", "请选择要上传的文件");
                return result;
            }

            // 2. 验证文件类型（仅允许图片）
            String contentType = file.getContentType();
            if (contentType == null || !contentType.startsWith("image/")) {
                result.put("success", false);
                result.put("message", "请上传图片类型文件（JPG、PNG等）");
                return result;
            }

            // 3. 验证文件大小（限制5MB以内）
            if (file.getSize() > 5 * 1024 * 1024) {
                result.put("success", false);
                result.put("message", "文件大小不能超过5MB");
                return result;
            }

            // 4. 处理文件路径和名称
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));

            // 生成唯一文件名（UUID）
            String fileName = UUID.randomUUID().toString() + extension;

            // 按日期创建文件夹（格式：yyyyMMdd）
            String dateDir = new SimpleDateFormat("yyyyMMdd").format(new Date());

            // 处理路径分隔符，兼容Windows和Linux
            File dateDirFile = new File(uploadPath + File.separator + dateDir);

            // 确保目录存在（递归创建）
            if (!dateDirFile.exists()) {
                boolean created = dateDirFile.mkdirs();
                if (!created) {
                    result.put("success", false);
                    result.put("message", "无法创建上传目录，请检查路径权限: " + dateDirFile.getAbsolutePath());
                    return result;
                }
            }

            // 检查目录是否可写
            if (!dateDirFile.canWrite()) {
                result.put("success", false);
                result.put("message", "上传目录不可写，请检查权限: " + dateDirFile.getAbsolutePath());
                return result;
            }

            // 完整文件路径
            File destFile = new File(dateDirFile, fileName);

            // 5. 保存文件到本地
            try {
                file.transferTo(destFile);
            } catch (FileNotFoundException e) {
                result.put("success", false);
                result.put("message", "文件路径不存在: " + destFile.getAbsolutePath());
                return result;
            }

            // 6. 生成访问URL（格式：/avatar/20250918/xxx.jpeg）
            String avatarUrl = accessUrl + dateDir + "/" + fileName;

            // 7. 返回成功结果
            result.put("success", true);
            result.put("avatarUrl", avatarUrl);  // 前端直接使用该URL访问头像
            result.put("message", "上传成功");
            System.out.println("头像上传成功，访问URL: " + avatarUrl);

        } catch (IOException e) {
            result.put("success", false);
            result.put("message", "文件上传失败: " + e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "服务器处理异常: " + e.getMessage());
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 头像访问接口
     * 匹配路径：GET /avatar/{dateDir}/{fileName}
     * 例如：/avatar/20250918/30a7a66b-ae4b-4855-b54b-029dbb73be38.jpeg
     */
    @GetMapping("/avatar/{dateDir}/{fileName:.+}")
    public ResponseEntity<byte[]> getAvatar(
            @PathVariable String dateDir,
            @PathVariable String fileName) {
        try {
            // 1. 安全验证：防止路径遍历攻击
            // 验证日期格式（必须是8位数字，如20250918）
            if (!dateDir.matches("\\d{8}")) {
                return ResponseEntity.badRequest().body(null);
            }
            // 验证文件名格式（UUID+扩展名，允许包含短横线）
            if (!fileName.matches("[0-9a-fA-F-]+\\.[a-zA-Z0-9]+")) {
                return ResponseEntity.badRequest().body(null);
            }

            // 2. 构建本地文件路径
            Path filePath = Paths.get(uploadPath)
                    .resolve(dateDir)  // 日期目录
                    .resolve(fileName)  // 文件名
                    .normalize();  // 规范化路径，防止../等攻击

            // 3. 检查文件是否存在
            if (!Files.exists(filePath)) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);  // 404文件不存在
            }

            // 4. 读取文件并返回
            String contentType = Files.probeContentType(filePath);
            if (contentType == null) {
                contentType = MediaType.IMAGE_JPEG_VALUE;  // 默认按图片类型处理
            }

            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .body(Files.readAllBytes(filePath));

        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);  // 500服务器错误
        }
    }
}
